// @Author : zaniu(zzaniu@126.com)
// @Time   : 2021/9/5 21:47
// @Desc   :
//
//                   _ooOoo_
//                  o8888888o
//                  88" . "88
//                  (| -_- |)
//                  O\  =  /O
//               ____/`---'\____
//             .'  \\|     |//  `.
//            /  \\|||  :  |||//  \
//           /  _||||| -:- |||||-  \
//           |   | \\\  -  /// |   |
//           | \_|  ''\---/''  |   |
//           \  .-\__  `-`  ___/-. /
//         ___`. .'  /--.--\  `. . __
//      ."" '<  `.___\_<|>_/___.'  >'"".
//     | | :  `- \`.;`\ _ /`;.`/ - ` : | |
//     \  \ `-.   \_ __\ /__ _/   .-` /  /
// =====`-.____`-.___\_____/___.-`____.-'=====
//                   `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//           佛祖保佑       永无BUG
//
package main

import (
	"context"
	"distributedTransaction/proto2go"
	"distributedTransaction/utils"
	"distributedTransaction/utils/nacos"
	"fmt"
	"google.golang.org/grpc"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"log"
	"net"
	"os"
	"os/signal"
)

var userMap = map[string]string{
	"zhangsan": "123456",
	"lisi":     "123456",
	"wangwu":   "123456",
	"daye":     "123456",
	"shadiao":  "123456",
}

type UserServer struct{}

func (u UserServer) Login(ctx context.Context, Request *proto2go.LoginRequest) (*proto2go.LoginReply, error) {
	user := Request.UserName
	pwd := Request.PassWd
	if len(pwd) > 0 && pwd == userMap[user] {
		token, err := utils.CreateJwtToken(user)
		if err != nil {
			fmt.Println("生成token失败，err = ", err)
			return &proto2go.LoginReply{}, status.Errorf(codes.Unknown, "系统不小心打了个盹，稍后重试")
		}
		return &proto2go.LoginReply{Message: "登录成功", Token: token}, nil
	}
	return &proto2go.LoginReply{}, status.Errorf(codes.NotFound, "用户名或密码错误")
}

func (u UserServer) AuthToken(ctx context.Context, Request *proto2go.AuthRequest) (*proto2go.AuthReply, error) {
	claims, err := utils.ParseJwtToken(Request.Token)
	if err != nil {
		fmt.Println("token校验失败, err = ", err.Error())
		return &proto2go.AuthReply{Ok: false}, status.Errorf(codes.DeadlineExceeded, "无效的token")
	}
	return &proto2go.AuthReply{Ok: true, UserName: claims.UserName}, nil
}

func (u UserServer) LogOut(ctx context.Context, Request *proto2go.LogOutRequest) (*proto2go.LogOutReply, error) {
	fmt.Printf("用户`%s`注销登录成功", Request.UserName)
	return &proto2go.LogOutReply{}, nil
}

func register(ip string, port uint64, serverName string) {
	ok, err := nacos.Register(ip, uint64(port), serverName)
	if err != nil || !ok {
		fmt.Println("注册失败, err = ", err.Error())
		os.Exit(-1)
	}
	fmt.Println("注册成功")
}

func deregister(ip string, port uint64, serverName string) {
	nacos.Deregister(ip, port, serverName)
}

func main() {
	ip := "127.0.0.1"
	port := 8082
	serverName := "gmb.go.user"
	nacos.ListenServerConfig("dev-data", "dev-group", &utils.GlobalServerConfig)
	register(ip, uint64(port), serverName)
	userServer := grpc.NewServer()
	proto2go.RegisterUserServer(userServer, UserServer{})
	listen, err := net.Listen("tcp", fmt.Sprintf("%s:%d", ip, port))
	defer listen.Close()
	if err != nil {
		panic("net.Listen err: " + err.Error())
	}
	// 运行服务
	go func() {
		if err := userServer.Serve(listen); err != nil {
			panic("server.Serve err: " + err.Error())
		}
	}()
	quit := make(chan os.Signal)
	signal.Notify(quit, os.Interrupt)
	<-quit
	nacos.CancelListenConfig("dev-data", "dev-group")
	deregister(ip, uint64(port), serverName)
	userServer.GracefulStop()
	log.Println("服务退出 ...")
}
